package com.stu.stusystem.controller.chat;

import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.stu.stusystem.model.chat.ChatMsg;
import com.stu.stusystem.service.chat.ChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: cxt
 * @time: 2021/6/9
 * websocket 请求
 */
@Slf4j
@Component
@ServerEndpoint("/stu/chat/{name}")
public class ChatController {

    private static ChatService chatMsgService;

    @Autowired
    public void setChatService(ChatService chatService) {
        ChatController.chatMsgService = chatService;
    }

    private static final Map<String, Session> clients = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam("name") String name, Session session) {
        log.info("有新的连接：{}", name);
        add(name, session);
        log.info("当前在线用户数：{}", clients.size());
    }

    /**
     * 发送消息，前端将消息转成json字符串，后端转成对象
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            ChatMsg msg = mapper.readValue(message, ChatMsg.class);
            if ("1".equals(msg.getSendType())) {
                // 广播
                sendMessageAll(msg.getMsg(), msg.getSendUser());
            } else if ("2".equals(msg.getSendType())) {
                // 群聊
                sendMessageGroup(msg.getMsg(), msg.getMsg());
            } else if ("3".equals(msg.getSendType())) {
                Session se = clients.get(msg.getAcceptUser());
                if (se != null) {
                    sendMessage(se, msg);
                } else {
                    msg.setIsRead("0");
                }
                // 保存消息
                chatMsgService.addMsg(msg);
            }
        } catch (JsonProcessingException e) {
            log.info("发送消息出错");
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(@PathParam("name") String name, Session session) {
        log.info("{}：退出聊天", name);
        remove(name);
        log.info("当前在线用户数：{}", clients.size());
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            session.close();
        } catch (IOException e) {
            log.error("退出发生异常： {}", e.getMessage());
        }
        log.info("连接出现异常： {}", throwable.getMessage());
    }

    /**
     * 新增一个连接
     */
    public static void add(String name, Session session) {
        if (!name.isEmpty() && session != null) {
            clients.put(name, session);
        }
    }

    /**
     * 删除一个连接
     */
    public static void remove(String name) {
        if (!name.isEmpty()) {
            clients.remove(name);
        }
    }

    /**
     * 获取在线人数
     */
    public static int count() {
        return clients.size();
    }

    /**
     * 广播
     *
     * @param message  发送的消息
     * @param username 发送人
     */
    public static void sendMessageAll(String message, String username) {
        log.info("广播消息:{}", message);
        clients.forEach((key, session) -> {
            if (!username.equals(key)) {
                RemoteEndpoint.Async remote = session.getAsyncRemote();
                if (remote == null) {
                    return;
                }
                remote.sendText(message);
            }
        });
    }

    /**
     * 群聊
     *
     * @param message  发送的消息
     * @param username 发送人
     */
    public static void sendMessageGroup(String message, String username) {
        log.info("群发消息");
        clients.forEach((key, session) -> {
            if (!username.equals(key)) {
                RemoteEndpoint.Async remote = session.getAsyncRemote();
                if (remote == null) {
                    return;
                }
                remote.sendText(message);
            }
        });
    }

    /**
     * 单聊
     *
     * @param session session
     * @param msg     发送的消息
     */
    public static void sendMessage(Session session, ChatMsg msg) {
        if (session == null) {
            return;
        }
        final RemoteEndpoint.Async basic = session.getAsyncRemote();
        if (basic == null) {
            return;
        }
        String s = JSONArray.toJSON(msg).toString();
        basic.sendText(s);
    }
}
